<?php
class Review extends AppModel
{
	var $name = 'Review';
	const PUBLISHED = 1;
	const UNPUBLISHED = 0;
	
	
	var $scopes = array(
		'published' => array('Review.status'=>Review::PUBLISHED)
	);
	
	var $hasMany = array(
					'ReviewComment'=>array(
							'className'=>'ReviewComment',
							'foreignKey'=>'review_id',
							'dependent'=>true
							),
					'Vote'=>array(
							'className'=>'Votes.Vote',
							'foreignKey'=>'item_id',
							'dependent'=>true
							)
					);
	
	
	var $belongsTo  = array(
						'Listing'=>array(
								'counterCache'=>true,
								'counterScope'=>array('Review.status'=>self::PUBLISHED,'not'=>array('Review.is_editorial'=>1))
								),
						'User'=>array(
								'className'=>"Users.User",
								'counterCache'=>true,
								'counterScope'=>array('Review.status'=>self::PUBLISHED)
								)
					);
	var $actsAs = array(
				'Comments.Commentable'=>array('commentModel'=>'ReviewComment','dependent'=>true),
				'Eav.Eav'=>array('dynamicRow'=>true, 'initCallback' => true),
				'Feature'=>array('limit'=>null),
				'Cms.Metric'=>array(
								array('metric'=>'NumRecords')
							),
				'Users.UserContent' => array(
							'badwordFilter' => true, 
							'fieldsToFilter' => array('title','body'),
							'posterModels'=>array('Users.User'=>array('dependent'=>true),'Users.Guest')	
				),
        'AutoModerator.AutoModerator'=> array() 
		);
	
	var $categoryId ;
	var $ListCategory;
	function initialize()
	{
		$this->additionalFields[] = 'viewUrl';
		$this->additionalFields[] = 'avg_score';
		$this->additionalFields[] = 'listing_image';
		$this->additionalFields[] = 'user_image';
		parent::initialize();
	}
	var $cachedFieldProperties = array();
	var $cacheFields = array(
							'avg_score'=>'onUpdate',
							'listing_image'=>'onUpdate',
						);
	var $fieldProperties = array(
							'title'=>array(
								'label'=>'Title',
								'type'=>'text',
								'group'=>array('add'),
								'validate'=>array(array('rule'=>VALID_NOT_EMPTY,'message'=>'This field is required')),
								),
							'body'=>array(
								'label'=>'Review',
								'type'=>'text',
								'rows'=>10,
								'group'=>array('add'),
								'validate'=>array(array('rule'=>VALID_NOT_EMPTY,'message'=>'This field is required')),
							),							
						);
	const EDITORIAL = 1;
	const RATING_MAX_VALUE = 5;	
	
	function listing_image($result)
	{
		$listingImage = $this->Listing->field('image',array('Listing.id'=>$result[$this->alias]['listing_id']));
		return $listingImage;	
	}
	
	function user_image($result)
	{
		$userImage = '';
		if(isset($result[$this->alias]['poster']['avatar']))
		{
			$userImage = $result[$this->alias]['poster']['avatar'];
		}
		return $userImage;
	}
	
	function getRecent($type = null, $limit = null)
	{
		$recentReviews= array();
		if(!empty($type) && !empty($limit))
		{		
			$recentReviews = $this->find('all',array('conditions'=>array('Review.type'=>$type,'Review.status'=>self::PUBLISHED),'limit'=>$limit,'order'=>array('Review.created DESC')));
			$recentReviews;
		}
		return $recentReviews;
	}
	
	function viewUrl($result)
	{
		$url = '/reviews/view/'.$result['Review']['id'];
		return $url;	
		
	}
	
	function avg_score($result)
	{
		$FieldPropertyObject = $this->getAttributes($result);
		$ratingFields = $FieldPropertyObject->getFields('type','rating');
		$weightageTotal = $grandTotal = $sum = 0;
		$noField = 0;
		foreach($ratingFields as $index=>$field)
		{
			if(!isset($result[$this->alias][$field]))
			{
				$noField = $noField+1;
				continue;
			}		
			$weight[$index] = $FieldPropertyObject->getPropertyValue($field,'weight');
			//if no value set it as 1
			if(!$weight[$index])
			{
				$weight[$index] = 1;
			}
			$weightageTotal += $weight[$index]; 
			$sum = $result[$this->alias][$field]; 
			if($weight[$index])
			{
				$sum = $result[$this->alias][$field]*$weight[$index];
			}
			$grandTotal += $sum;			
		}	
		if($noField == count($ratingFields))
		{
			return false;
		}
		if($weightageTotal==0)
		{
			$weightageTotal = 1;
		}
		$avgScore = ($grandTotal/$weightageTotal);	
		return number_format($avgScore,1);
		
	}
		
	function beforeSave($options)
	{
		$isAdmin = false;
		if(isset($this->data[$this->alias]['admin']) || count($this->data[$this->alias]) == 2)
		{
			$isAdmin = true;
			unset($this->data[$this->alias]['admin']);
		}
		if(isset($this->data[$this->alias]['fake']))
		{
			unset($this->data[$this->alias]['fake']);
		}
			
		if($isAdmin == false)
		{
			$reviewConfig = cr("ReviewConfig");
			$isEditor = $this->User->isEditor($this->data['Review']['user_id']);
			if($this->_isNew())
			{
				if(!isset($this->data['Review']['added_with_listing']) || !$this->data['Review']['added_with_listing']) //added for review added with listing
				{
					if($isEditor)
					{
						//only add is Editorial if editor review is enabled.
						if($this->hasEditorReviewed($this->data['Review']['listing_id']) == false && !cr('GeneralConfig.disable_editor_reviews'))
						{
							$this->data['Review']['is_editorial'] = self::EDITORIAL;
						}						
						if($reviewConfig['moderate_new_editor_reviews'] == false)
						{
							$this->data['Review']['status'] = self::PUBLISHED;
						}			
					}else
					{
						if($reviewConfig['moderate_new_user_reviews'] == false)
						{
							$this->data['Review']['status'] = self::PUBLISHED;
						}
					}
				}
			}else
			{
				//in case of editing a review
				if($isEditor)
				{
					if($reviewConfig['moderate_edited_editor_reviews'] == true)
					{
						$this->data['Review']['status'] = self::UNPUBLISHED;
					}
				}else
				{
					if($reviewConfig['moderate_edited_user_reviews'] == true)
					{
						$this->data['Review']['status'] = self::UNPUBLISHED;
					}
				}			
			}				
		}
		//prd($this->data);
		
		if($this->_isNew() && isset($this->data[$this->alias]['listing_id']))
		{
			$listCategoryId = $this->Listing->field('list_category_id',array('Listing.id'=>$this->data[$this->alias]['listing_id']));
			$this->data[$this->alias]['list_category_id'] = $listCategoryId; 
		}
		
		return parent::beforeSave($options);
	}
	
	function hasEditorReviewed($listingId = null)
	{
		return $this->hasAny(array('listing_id'=>$listingId,'is_editorial'=>self::EDITORIAL));
	}
	
	function isEditorialReview($reviewId = null)
	{
		return $this->hasAny(array('Review.id'=>$reviewId,'is_editorial'=>self::EDITORIAL));
	}
	
	function setCategoryId($categoryId,$refresh = true)
	{
		$this->categoryId = $categoryId;
		if($refresh)
		{
			$this->refreshFieldProperties();
			unset($this->_distinctFieldTypes);
			GigaFieldTypesHandler::trigger($this->getDistinctFieldTypes(), 'onModelInitialize', array($this));
		}
	}
	
	function hasReviewed($lisitingId,$userId)
	{
		if(empty($userId))
		{
			return false;
		} 
		return $this->hasAny(array('listing_id'=>$lisitingId,'user_id'=>$userId));
	}
	
	function afterSave($created)
	{
		//@todo fix this hack as $this->data becomes empty in afterSave.Issue is related to even listner.
		$reveiwData = $this->data;
		parent::afterSave($created);
		$this->data = $reveiwData;
		
		$listCategoryId = null;
		$listingId = null;		
		
		if(isset($this->data[$this->alias]['listing_id']))
		{
			$listingId = $this->data[$this->alias]['listing_id'];
		}
		if(!$listingId)
		{
			$listingId = $this->field('listing_id',array('Review.id'=>$this->id));
		}
		$listCategoryId = $this->field('list_category_id',array('Review.id'=>$this->id));
		$this->setCategoryId($listCategoryId,false);
		$FieldPropertiesObject = $this->getAttributes();
		$eavFields = array_intersect(array_keys($this->data[$this->alias]),$FieldPropertiesObject->getFields('type',SCHEMA_TYPE_RATING));
			
		if(count($eavFields)> 0 || isset($this->data[$this->alias]['status']))
		{
			$reviewId = $this->id;
			$this->Listing->saveRatingAverages($listingId);
			//might get changed in recursive call. 
			$this->id = $reviewId;
		}
		$this->Listing->clearRecordCache($listingId);
	}
	
	function getAttributes($result = null)
	{		
		if(isset($result[$this->alias]['list_category_id']))
		{
			$this->categoryId = $result[$this->alias]['list_category_id'];
		}
		if(!isset($this->cachedFieldProperties[$this->categoryId]))
		{
			if(!class_exists('Fieldset'))
			{
				App::import('Model','Eav.Fieldset');
			}
			$customFields = $this->ListCategory->getCustomFields($this->categoryId,Fieldset::TYPE_REVIEW);
            if(!class_exists('ListingFieldProperties'))
            {
              App::import("Vendor",'ListingFieldProperties');
            }
			$this->cachedFieldProperties[$this->categoryId] = new ListingFieldProperties($customFields);
		}
		return $this->cachedFieldProperties[$this->categoryId];
	}
	
	function afterInitialize()
	{
		parent::afterInitialize();
		$this->ListCategory = cri('ListCategory');
		if(cr('ReviewConfig.upload_assets'))
		{
			$this->setFieldProperties('assets', array(
								'label'=>"Images",
								'type'=> 'parent',
								'childInfo' => array(
											'model' => 'ListingAsset',
											'child_group' => 'add',
											'allowMultiple' => true,
											'deleteMissing' => false,
										),
									'fieldset' => false,
									'addMoreLabel'=>__("Add more Images")
							));
			$this->additionalFields[] = 'listing_asset_count';
			$this->cacheFields['listing_asset_count']= '+30 minutes';
		}
	}
	function getTextSearchCondition($keyword)
	{
		//if(strlen($keyword) <= 3)
		{
			$condition['OR'] = array('Review.body like'=>"%$keyword%");
		}//else
		{
			//$keyword = mysql_real_escape_string($keyword);
			//$condition = array('Match(Listing.description,Listing.title,Listing.summary) AGAINST("'.$keyword.'") ');
		}
		return $condition;
	}
	
	function getEditorialReview($listingId)
	{
		$editorialReview = $this->find('first',array('conditions'=>array('Review.listing_id'=>$listingId,'Review.is_editorial'=>1,'Review.status'=>self::PUBLISHED),'recursive'=>0));
		return $editorialReview;
	}
	function beforeDelete($cascade)
	{
		$this->listingId = $this->field('listing_id',array('Review.id'=>$this->id));
		return parent::beforeDelete($cascade);	
	}
	
	function afterDelete()
	{
		$listingId = $this->listingId;
		$this->Listing->saveRatingAverages($listingId);
		parent::afterDelete();	
	}
	/**
	 * Total images uploaded by reviewer
	 * Enter description here ...
	 */	
	function listing_asset_count($review)
	{
		$listingCount = false;
		if(isset($review[$this->alias]['listing_id']) && $review[$this->alias]['user_id'])
		{
			$ListingAsset = cri("ListingAsset");
			$listingCount = $ListingAsset->find("count",array("conditions"=>array("user_id"=>$review[$this->alias]['user_id'],'listing_id'=>$review[$this->alias]['listing_id'],'status'=>ListingAsset::PUBLISHED),'recursive'=>-1));
			if(AppUtility::allowPaidListing())
			{
				$EffectivePlan = cri("PaidListings.ListingPlan")->getEffectivePlan($review[$this->alias]['listing_id']);
				if($EffectivePlan->limitImages())
				{
					$allowedImagesCount = $EffectivePlan->getAllowedTotalImagesCount();
					if($allowedImagesCount > 0 && $listingCount > $allowedImagesCount)
					{
						$listingCount = $allowedImagesCount;
					}
				}
			}
		}
		return $listingCount;
	}
  
  function onAutoModeration(AppModel $ParentModel,$parentId,$moderatedIds,$statusValue)
  {
      if($ParentModel instanceof Listing && $statusValue == 1)
      {
          $this->Listing->saveRatingAverages($parentId);
          $this->Listing->clearRecordCache($parentId);
      }
  }
}
?>